# ------------------------------------------------------------------------------------
# Helper to use RobWork from outside project
#
# set ROBWORKSTUDIO_DIR to installation path to find root of sdurw, else automatic finding will be used
# based on RobWorkStudio_DIR
#
# ROBWORKSTUDIO_LIBRARIES is filled with all available RobWork libraries ROBWORKSTUDIO_INCLUDE_DIRS
# is filled with RobWorkStudio and available 3rdparty headers ROBWORKSTUDIO_LIBRARY_DIRS is filled
# with RobWorkStudio components libraries install directory and 3rdparty libraries paths
#
# www.robwork.dk
# ------------------------------------------------------------------------------------

# ---[ Find RobWorkStudio

if(ROBWORKSTUDIO_FIND_QUIETLY)
    set(QUIET_ QUIET)
else(ROBWORKSTUDIO_FIND_QUIETLY)
    set(QUIET_)
endif(ROBWORKSTUDIO_FIND_QUIETLY)

# ############################################# MACROS ########################################

# macro for determining the best RobWork build type match
macro(GET_ROBWORKSTUDIO_BUILD_TYPE CFG_ROOT RWS_BUILD_TYPE)
    # defaults to release
    set(BTYPE_TMP release)
    if(CMAKE_BUILD_TYPE)
        string(TOLOWER ${CMAKE_BUILD_TYPE} BTYPE_TMP)
    else()
        set(BTYPE_TMP "none")
    endif()

    # first test if the correct cmake build type is installed
    if(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_${BTYPE_TMP}.cmake)
        set(${RWS_BUILD_TYPE} ${BTYPE_TMP})
    else()

        # find best RobWorkStudio build match
        if(${BTYPE_TMP} STREQUAL "release")
            # find release compatible RobWorkStudio installation
            if(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_minsizerel.cmake)
                set(${RWS_BUILD_TYPE} minsizerel)
            elseif(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_relwithdebinfo.cmake)
                set(${RWS_BUILD_TYPE} relwithdebinfo)
            elseif(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_debug.cmake)
                set(${RWS_BUILD_TYPE} debug)
            elseif(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_none.cmake)
                set(${RWS_BUILD_TYPE} none)
            else()
                message(FATAL_ERROR "Could not find any build of RobWorkStudio!")
            endif()
        elseif(${BTYPE_TMP} STREQUAL "minsizerel")
            if(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_release.cmake)
                set(${RWS_BUILD_TYPE} release)
            elseif(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_relwithdebinfo.cmake)
                set(${RWS_BUILD_TYPE} relwithdebinfo)
            elseif(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_debug.cmake)
                set(${RWS_BUILD_TYPE} debug)
            elseif(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_none.cmake)
                set(${RWS_BUILD_TYPE} none)
            else()
                message(FATAL_ERROR "Could not find any build of RobWorkStudio!")
            endif()
        elseif(${BTYPE_TMP} STREQUAL "relwithdebinfo")
            if(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_release.cmake)
                set(${RWS_BUILD_TYPE} release)
            elseif(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_minsizerel.cmake)
                set(${RWS_BUILD_TYPE} minsizerel)
            elseif(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_debug.cmake)
                set(${RWS_BUILD_TYPE} debug)
            elseif(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_none.cmake)
                set(${RWS_BUILD_TYPE} none)
            else()
                message(FATAL_ERROR "Could not find any build of RobWorkStudio!")
            endif()
        elseif(${BTYPE_TMP} STREQUAL "debug")
            if(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_relwithdebinfo.cmake)
                set(${RWS_BUILD_TYPE} relwithdebinfo)
            elseif(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_minsizerel.cmake)
                set(${RWS_BUILD_TYPE} minsizerel)
            elseif(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_release.cmake)
                set(${RWS_BUILD_TYPE} release)
            elseif(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_none.cmake)
                set(${RWS_BUILD_TYPE} none)
            else()
                message(FATAL_ERROR "Could not find any build of RobWorkStudio!")
            endif()
        elseif(${BTYPE_TMP} STREQUAL "none")
            if(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_relwithdebinfo.cmake)
                set(${RWS_BUILD_TYPE} relwithdebinfo)
            elseif(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_minsizerel.cmake)
                set(${RWS_BUILD_TYPE} minsizerel)
            elseif(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_release.cmake)
                set(${RWS_BUILD_TYPE} release)
            elseif(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_debug.cmake)
                set(${RWS_BUILD_TYPE} debug)
            else()
                message(FATAL_ERROR "Could not find any build of RobWorkStudio!")
            endif()
        else()
            message(
                STATUS
                    "Does not recognize build type: ${CMAKE_BUILD_TYPE} choosing any existing RobWorkStudio installation!"
            )
            if(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_release.cmake)
                set(${RWS_BUILD_TYPE} release)
            elseif(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_minsizerel.cmake)
                set(${RWS_BUILD_TYPE} minsizerel)
            elseif(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_relwithdebinfo.cmake)
                set(${RWS_BUILD_TYPE} relwithdebinfo)
            elseif(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_debug.cmake)
                set(${RWS_BUILD_TYPE} debug)
            elseif(EXISTS ${CFG_ROOT}/RobWorkStudioBuildConfig_none.cmake)
                set(${RWS_BUILD_TYPE} none)
            else()
                message(FATAL_ERROR "Could not find any build of RobWorkStudio!")
            endif()
        endif()

        message(
            STATUS
                "warning: RobWorkStudio was not compiled with type:${BTYPE_TMP} using type:${${RWS_BUILD_TYPE}} instead!"
        )
    endif()

endmacro()

macro(RWS_MESSAGE text)
    if(IS_INSTALL)
        message(STATUS ${text})
    endif()
endmacro()

# ##################################################################################################

set(RWSCFG_ROOT ${CMAKE_CURRENT_LIST_DIR})

# check if user specified a RobWorkStudio_DIR
if(DEFINED RobWorkStudio_DIR)
    if(EXISTS "${RobWorkStudio_DIR}/../src/RobWorkStudioConfig.hpp")
        # Found RobWorkStudio in a build tree of RobWork
        set(RWSCFG_ROOT "${RobWorkStudio_DIR}")
    elseif(EXISTS "${RobWorkStudio_DIR}/RobWorkStudioConfig.cmake")
        # Found a RobWorkStudio installation
        set(RWSCFG_ROOT "${RobWorkStudio_DIR}")
    elseif(
        EXISTS
        "${RobWorkStudio_DIR}/include/robworkstudio-${RobWorkStudio_VERSION_MAJOR}.${RobWorkStudio_VERSION_MINOR}/RobWorkStudioConfig.hpp"
    )
        set(RWSCFG_ROOT
            "${RobWorkStudio_DIR}/share/robworkstudio-${RobWorkStudio_VERSION_MAJOR}.${RobWorkStudio_VERSION_MINOR}"
        )
    else()
        # found no RobWorkStudio installation ot build tree in RobWorkStudio_DIR so we try
        # extracting it from RobWorkStudioConfig.cmake location instead
    endif()
    get_filename_component(RWSCFG_ROOT ${RWSCFG_ROOT} ABSOLUTE)
endif()

# get the relavant build type
get_robworkstudio_build_type(${RWSCFG_ROOT} RWS_BUILD_TYPE)

if(NOT TARGET sdurws)
    include("${RWSCFG_ROOT}/RobWorkStudioTargets.cmake")
endif()

# check whether RobWorkConfig.cmake is found into a RobWork installation or in a build tree
if(EXISTS "${RWSCFG_ROOT}/../src/RobWorkStudioConfig.hpp")
    # Found RobWorkConfig.cmake in a build tree of RobWork
    set(succmsg "RobWorkStudio: Found a RobWorkStudio build tree")
    set(RWS_ROOT "${RWSCFG_ROOT}/..")

    set(RWS_INCLUDE_EXT "${RWS_ROOT}/ext")
    set(RWS_INCLUDE_SRC "${RWS_ROOT}/src")
    set(RWS_LIBS "${RWS_ROOT}/libs/${RWS_BUILD_TYPE}")
    set(IS_INSTALL FALSE)
else()
    set(succmsg "RobWorkStudio: Found a RobWorkStudio installation")
    set(IS_INSTALL TRUE)
    # Found a RobWork installation
    if(WIN32)
        # RobWorkConfig.cmake is installed to RWS_ROOT/robworkstudio_MAJOR_MINOR/cmake
        set(RWS_ROOT "${RWSCFG_ROOT}/../..")
        set(RWS_INCLUDE_EXT "${RWS_ROOT}/../ext")
        set(RWS_INCLUDE_SRC "${RWS_ROOT}/include/robworkstudio-${RobWorkStudio_VERSION_MAJOR}.${RobWorkStudio_VERSION_MINOR}")
        set(RWS_LIBS "${RWS_ROOT}/lib")
    else()
        # RobWorkConfig.cmake is installed to RWS_INTALL/share/robworkstudio-x.y

        set(RWS_ROOT "${RWSCFG_ROOT}")
        set(RWS_INSTALL "${RWSCFG_ROOT}/../../..")
        set(RWS_LIBS "${RWS_INSTALL}/lib")
        set(
            RWS_INCLUDE_SRC
            "${RWS_INSTALL}/include/robworkstudio-${RobWorkStudio_VERSION_MAJOR}.${RobWorkStudio_VERSION_MINOR}"
        )
        set(
            RWS_INCLUDE_EXT
            "${RWS_INSTALL}/share/robworkstudio-${RobWorkStudio_VERSION_MAJOR}.${RobWorkStudio_VERSION_MINOR}/ext"
        )
    endif()
endif()

include(${RWSCFG_ROOT}/RobWorkStudioMacros.cmake)

# ##################################################################################################
# now RWS_ROOT and RWSCFG_ROOT is set. Lets extract the stuff needed to run a project

# next get the build configuration of the requested built type
if(EXISTS ${RWSCFG_ROOT}/RobWorkStudioBuildConfig_${RWS_BUILD_TYPE}.cmake)
    include(${RWSCFG_ROOT}/RobWorkStudioBuildConfig_${RWS_BUILD_TYPE}.cmake)

    set(BOOST_ROOT ${RWS_BUILD_WITH_BOOST_ROOT})
    set(BOOST_INCLUDEDIR ${RWS_BUILD_WITH_BOOST_INCLUDE_DIR})
    set(BOOST_LIBRARYDIR ${RWS_BUILD_WITH_BOOST_LIBRARY_DIR})

    if(DEFINED WIN32 AND ${IS_INSTALL})
        set(BOOST_INCLUDEDIR "${RW_INCLUDE_EXT}/boost")
        set(BOOST_LIBRARYDIR "${RW_LIBS}")
    endif()

    # Find libraries
    set(ROBWORKSTUDIO_LIBRARIES_TMP)
    foreach(lib IN LISTS RWS_BUILD_WITH_LIBRARIES)
        unset(FOUND CACHE)
        find_library(
            FOUND ${lib}
            PATHS ${RWS_LIBS}
            PATH_SUFFIXES ${RWS_BUILD_WITH_LIBRARY_SUBDIRS}
            NO_DEFAULT_PATH
        )
        if(FOUND)
            list(APPEND ROBWORKSTUDIO_LIBRARIES_TMP "${lib}")
            rws_message("Looking for ${lib} - found")
        else()
            if(${lib} STREQUAL "sdurws")
                list(APPEND ROBWORKSTUDIO_LIBRARIES_TMP "${lib}")
                rws_message("Looking for ${lib} - not found")
            else()
                rws_message("Looking for ${lib} - not found (ignored)")
            endif()
        endif()
    endforeach()

    # Set extra compiler flags. The user should be able to change this
    set(RWS_CXX_FLAGS ${RWS_BUILD_WITH_CXX_FLAGS} CACHE STRING "Change this to force using your own
                    flags and not those of RobWorkStudio")
    set(
        RWS_DEFINITIONS
        ${RWS_BUILD_WITH_DEFINITIONS}
        CACHE STRING "Change this to force using your own
                    definitions and not those of RobWork"
    )
    add_definitions(${RWS_DEFINITIONS})
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${RWS_CXX_FLAGS}")

    # Set extra linker flags. The user should be able to change this
    set(
        RWS_LINKER_FLAGS
        ${RWS_BUILD_WITH_LINKER_FLAGS}
        CACHE STRING "Change this to force using your own linker
                    flags and not those of RobWork"
    )
    set(
        CMAKE_SHARED_LINKER_FLAGS
        "${CMAKE_SHARED_LINKER_FLAGS} ${RWS_LINKER_FLAGS}"
        CACHE STRING "" FORCE
    )
    set(
        CMAKE_MODULE_LINKER_FLAGS
        "${CMAKE_MODULE_LINKER_FLAGS} ${RWS_LINKER_FLAGS}"
        CACHE STRING "" FORCE
    )
    if(WIN32)
        set(
            CMAKE_EXE_LINKER_FLAGS
            "${CMAKE_EXE_LINKER_FLAGS} ${RWS_LINKER_FLAGS}"
            CACHE STRING "" FORCE
        )
    endif()


    cmake_minimum_required(VERSION 3.5.1)
    set(CMAKE_MODULE_PATH ${RWSCFG_ROOT}/Modules ${CMAKE_MODULE_PATH})
    
    find_package(Qt5Core REQUIRED)
    find_package(Qt5Gui REQUIRED)
    find_package(Qt5Widgets REQUIRED)
    find_package(Qt5OpenGL REQUIRED)
    get_target_property(QT_UIC_EXECUTABLE Qt5::uic LOCATION)
    set(QT_LIBRARIES ${Qt5Core_LIBRARIES} ${Qt5Gui_LIBRARIES} ${Qt5Widgets_LIBRARIES}
                     ${Qt5OpenGL_LIBRARIES})
    set(QT_INCLUDES ${Qt5Core_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS}
                    ${Qt5OpenGL_INCLUDE_DIRS})
    # include_directories(${QT_INCLUDES})

    # Find and setup OpenGL.
    if(POLICY CMP0072) # Introduce cmake 3.11
        cmake_policy(SET CMP0072 NEW)
    endif()
    find_package(OpenGL REQUIRED)

    if(${RWS_BUILD_WITH_PYTHON})
        find_package(PythonLibs ${RWS_BUILD_WITH_PYTHONLIBS_MAJOR_VERSION} REQUIRED)
        find_package(PythonInterp ${RWS_BUILD_WITH_PYTHON_MAJOR_VERSION} REQUIRED)
    endif()

    if(${RWS_BUILD_WITH_FREEGLUT})
        find_package(FreeGLUT REQUIRED)
    endif()

    # Find RobWork
    if(NOT DEFINED RobWork_FOUND OR NOT ${RobWork_FOUND})
        if(${IS_INSTALL})
            find_package(RobWork QUIET)
        else()
            set(RobWork_FOUND FALSE)
        endif()
        
        if(NOT ${RobWork_FOUND})
            find_package(RobWork REQUIRED HINTS ${RWS_BUILD_WITH_RW_ROOT}/cmake)
        endif()
    else()
        message(STATUS "RobWork Already Found")
    endif()

    set(ROBWORKSTUDIO_BUILD_PATH "${RWS_BUILD_WITH_RWS_ROOT}")
    set(ROBWORKSTUDIO_INCLUDE_DIRS_TMP "${PYTHON_INCLUDE_DIRS}" "${RWS_BUILD_WITH_INCLUDE_DIR}"
                                       "${ROBWORK_INCLUDE_DIR}")
    set(ROBWORKSTUDIO_LIBRARY_DIRS_TMP "${RWS_BUILD_WITH_LIBRARY_DIRS}" "${ROBWORK_LIBRARY_DIRS}")
    set(ROBWORKSTUDIO_LIBRARIES "${ROBWORKSTUDIO_LIBRARIES_TMP}" "${ROBWORK_LIBRARIES}"
                                "${RWS_BUILD_WITH_LIB_DEPEND}" "${PYTHON_LIBRARIES}")
    list(REMOVE_DUPLICATES ROBWORKSTUDIO_LIBRARIES)

    # make sure that the library and include paths are pointing to the right locations
    string(
        REPLACE
            "${ROBWORKSTUDIO_BUILD_PATH}/ext" "${RWS_INCLUDE_EXT}" ROBWORKSTUDIO_INCLUDE_DIRS
            "${ROBWORKSTUDIO_INCLUDE_DIRS_TMP}"
    )
    string(
        REPLACE
            "${ROBWORKSTUDIO_BUILD_PATH}/src" "${RWS_INCLUDE_SRC}" ROBWORKSTUDIO_INCLUDE_DIRS
            "${ROBWORKSTUDIO_INCLUDE_DIRS}"
    )
    if(WIN32)
        list(APPEND ROBWORKSTUDIO_INCLUDE_DIRS "${RWS_INCLUDE_EXT}")
    endif()

    list(REMOVE_DUPLICATES ROBWORKSTUDIO_INCLUDE_DIRS)

    string(
        REPLACE
            "${ROBWORKSTUDIO_BUILD_PATH}/libs/${RWS_BUILD_TYPE}" "${RWS_LIBS}"
            ROBWORKSTUDIO_LIBRARY_DIRS "${RWS_BUILD_WITH_LIBRARY_DIRS}"
    )
    if(${IS_INSTALL} AND DEFINED WIN32)
        string(REPLACE "${RWS_BUILD_WITH_BOOST_LIBRARY_DIR}/" "" ROBWORKSTUDIO_LIBRARIES
                    "${ROBWORKSTUDIO_LIBRARIES}"
        )
    endif()
    list(REMOVE_DUPLICATES ROBWORKSTUDIO_LIBRARY_DIRS)

    # Find and add full path information for the RobWorkStudio libraries
    set(ROBWORKSTUDIO_LIBRARIES_TMP ${ROBWORKSTUDIO_LIBRARIES})
    set(ROBWORKSTUDIO_LIBRARIES)
    foreach(l ${ROBWORKSTUDIO_LIBRARIES_TMP})
        unset(tmp CACHE)
        find_library(
            tmp ${l}
            PATHS ${RWS_LIBS} ${RW_LIBS}
            PATH_SUFFIXES ${RWS_BUILD_WITH_LIBRARY_SUBDIRS}
            NO_DEFAULT_PATH
        )
        if(tmp)
            list(APPEND ROBWORKSTUDIO_LIBRARIES ${tmp})
        else()
            list(APPEND ROBWORKSTUDIO_LIBRARIES ${l})
        endif()
    endforeach(l)

else()
    message(STATUS "RobWorkStudio: Could not find a suitable RobWorkStudio installation!")
endif()

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
    RobWorkStudio
    "Found RobWorkStudio-Version ${RobWorkStudio_VERSION}"
    RWS_ROOT
    ROBWORKSTUDIO_LIBRARIES
    ROBWORKSTUDIO_INCLUDE_DIRS
    ROBWORKSTUDIO_LIBRARY_DIRS
)
mark_as_advanced(ROBWORKSTUDIO_LIBRARIES ROBWORKSTUDIO_INCLUDE_DIRS ROBWORKSTUDIO_LIBRARY_DIRS)

if(ROBWORKSTUDIO_FOUND)
    set(ROBWORKSTUDIO_VERSION ${RobWorkStudio_VERSION} CACHE STRING "RobWorkStudio version")
endif(ROBWORKSTUDIO_FOUND)
